#include <stack>
#include <string>

#include "BrowseForFolderDialog.h"
#include "Resources.h"

using namespace std;

BrowseForFolderDialog::BrowseForFolderDialog(HINSTANCE hInstance, const TCHAR *caption) throw(): Dialog(hInstance, caption, CS_OKCANCEL) {
    m_hFolders = CreateWindow(WC_TREEVIEW, TEXT("TreeView"), WS_BORDER | WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SINGLEEXPAND, widthToPixels(-1), heightToPixels(-1), widthToPixels(width() + 2), heightToPixels(height() - 20 + 1), hWnd(), 0, hInstance, 0);
    m_hFileName = CreateWindow(TEXT("EDIT"), 0, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_LEFT, widthToPixels(4), heightToPixels(height() - 16), widthToPixels(width() - 8), heightToPixels(12), hWnd(), 0, hInstance, 0);

    int iconWidth = GetSystemMetrics(SM_CXSMICON);
    int iconHeight = GetSystemMetrics(SM_CYSMICON);
    m_hImages = ImageList_Create(iconWidth, iconHeight, ILC_MASK | ILC_COLORDDB, 1, 1);
    ImageList_AddIcon(m_hImages, HICON(LoadImage(hInstance, MAKEINTRESOURCE(ID_FOLDERICON), IMAGE_ICON, iconWidth, iconHeight, 0)));
    TreeView_SetImageList(m_hFolders, m_hImages, TVSIL_NORMAL);

    TCHAR root[MAX_PATH];
    SHGetSpecialFolderPath(hWnd(), root, CSIDL_PERSONAL, FALSE);

    addFolders(root, 0);
}

BrowseForFolderDialog::~BrowseForFolderDialog() {
    DestroyWindow(m_hFileName);
    DestroyWindow(m_hFolders);
    ImageList_Destroy(m_hImages);
}

const TCHAR *BrowseForFolderDialog::selectedFile() const throw() {
    return(m_file);
}

const TCHAR *BrowseForFolderDialog::selectedPath() const throw() {
    return(m_path);
}

bool BrowseForFolderDialog::close(CloseCommand cc) throw() {
    if(cc == CC_OK) {
        SendMessage(m_hFileName, WM_GETTEXT, MAX_PATH, LPARAM(m_file));
        if(_tcslen(m_file) == 0) {
            MessageBox(hWnd(), TEXT("You must provide a filename!"), TEXT("No filename!"), MB_OK | MB_ICONERROR);
            return(false);
        }

        HTREEITEM item = TreeView_GetSelection(m_hFolders);
        if(item == 0) {
            MessageBox(hWnd(), TEXT("You must select a folder in which to place the file!"), TEXT("No folder!"), MB_OK | MB_ICONERROR);
            return(false);
        }

        stack<basic_string<TCHAR> > pathStack;
        do {
            TCHAR folderName[MAX_PATH];
            TVITEM i;
            i.mask = TVIF_HANDLE | TVIF_TEXT;
            i.hItem = item;
            i.pszText = folderName;
            i.cchTextMax = MAX_PATH;
            TreeView_GetItem(m_hFolders, &i);
            pathStack.push(folderName);
        }
        while((item = TreeView_GetParent(m_hFolders, item)) != 0);

        SHGetSpecialFolderPath(hWnd(), m_path, CSIDL_PERSONAL, FALSE);
        while(!pathStack.empty()) {
            _tcscat(m_path, TEXT("\\"));
            _tcscat(m_path, pathStack.top().c_str());
            pathStack.pop();
        }

        return(true);
    }
    else {
        return(true);
    }
}

void BrowseForFolderDialog::controlNotification(HWND hWnd, WPARAM notification) throw() {
}

void BrowseForFolderDialog::menuNotification(unsigned int itemId) throw() {
}

void BrowseForFolderDialog::addFolders(const TCHAR *root, HTREEITEM parent) throw() {
    TCHAR path[MAX_PATH];
    _tcscpy(path, root);
    _tcscat(path, TEXT("\\*.*"));
    WIN32_FIND_DATA fd;
    HANDLE hFind = FindFirstFile(path, &fd);
    if(hFind != INVALID_HANDLE_VALUE) {
        do {
            if(fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY && fd.dwFileAttributes != FILE_ATTRIBUTE_HIDDEN && fd.dwFileAttributes != FILE_ATTRIBUTE_SYSTEM && fd.dwFileAttributes != FILE_ATTRIBUTE_TEMPORARY && fd.cFileName[0] != TEXT('.')) {
                TVINSERTSTRUCT is;
                is.hParent = parent;
                is.hInsertAfter = TVI_LAST;
                is.item.mask = TVIF_TEXT;
                is.item.pszText = fd.cFileName;
                HTREEITEM child = TreeView_InsertItem(m_hFolders, &is);

                TCHAR newRoot[MAX_PATH];
                _tcscpy(newRoot, root);
                _tcscat(newRoot, TEXT("\\"));
                _tcscat(newRoot, fd.cFileName);
                addFolders(newRoot, child);
            }
        }
        while(FindNextFile(hFind, &fd));
    }
}
